import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * GCUploadMojo Maven uploads arbitrary files to Google Code.
 *
 * @author Dmitry Korotkov
 * @goal gcupload
 * @since 1.0.5
 */
public class GCUploadMojo extends AbstractMojo {

    /**
     * Upload URL
     *
     * @parameter expression="${uploadUrl}"
     */
    private String uploadUrl;

    /**
     * Google Code user name
     *
     * @parameter expression="${userName}"
     * @required
     */
    private String userName;

    /**
     * Google Code password
     *
     * @parameter expression="${password}"
     * @required
     */
    private String password;

    /**
     * Files to upload
     *
     * @parameter
     * @required
     */
    private UploadItem[] uploadFiles;

    /**
     * Google Code project name
     *
     * @parameter expression="${projectName}"
     * @required
     */
    private String projectName;

    public void execute() throws MojoExecutionException, MojoFailureException {

        if (uploadUrl == null) {
            uploadUrl = "https://" + projectName + ".googlecode.com/files";
        }

        // Validate all files first

        for (UploadItem item : uploadFiles) {
            File file = new File(item.getFileName());
            if (!file.exists()) {
                throw new MojoFailureException(String.format("File '%s' not found", file.getAbsolutePath()));
            }
            if (file.isDirectory()) {
                throw new MojoFailureException(String.format("File '%s' is a directory", file.getAbsolutePath()));
            }
        }

        // Upload all files

        HttpClient httpClient = new DefaultHttpClient();
        Credentials credentials = new UsernamePasswordCredentials(userName, password);

        for (UploadItem item : uploadFiles) {
            File file = new File(item.getFileName());

            getLog().info(String.format("Uploading file '%s' to '%s'", file.getAbsolutePath(), uploadUrl));

            HttpPost httpPost = new HttpPost(uploadUrl);
            try {
                httpPost.addHeader(new BasicScheme().authenticate(credentials, httpPost));
            } catch (AuthenticationException e) {
                throw new MojoExecutionException("Failed to setup authentication", e);
            }

            FileBody fileBody = new FileBody(file);
            MultipartEntity multipartEntity = new MultipartEntity();
            multipartEntity.addPart("filename", fileBody);
            try {
                multipartEntity.addPart("summary", new StringBody(item.getSummary()));
                if (item.getDescription() != null) {
                    multipartEntity.addPart("description", new StringBody(item.getDescription()));
                }
                for (String label : item.getLabels()) {
                    multipartEntity.addPart("label", new StringBody(label));
                }
            } catch (UnsupportedEncodingException e) {
                throw new MojoExecutionException("Error creating request parameters", e);
            }
            httpPost.setEntity(multipartEntity);

            httpPost.addHeader("User-Agent", "RuSalad maven google code uploader plugin");
            HttpResponse httpResponse;
            try {
                httpResponse = httpClient.execute(httpPost);
                httpResponse.getEntity().consumeContent();
            } catch (IOException e) {
                throw new MojoExecutionException("HTTP request failed", e);
            }

            if (httpResponse.getStatusLine().getStatusCode() / 100 != 2) {
                throw new MojoFailureException(String.format("Upload failed. %d: %s", httpResponse.getStatusLine().getStatusCode(), httpResponse.getStatusLine().getReasonPhrase()));
            }
        }
        httpClient.getConnectionManager().shutdown();
    }
}
